Seperate Compile

헤더 파일(hpp)와 소스 파일(cpp)
C++에서 일반적으로 소스코드의 각 단위를 아래와 같이 나눈다.
- 선언문이 있는 헤더 파일(.hpp)
- 소스 파일(.cpp)

소스 파일은 실행 파일을 생성하는 모든 알고리즘의 구현부를 포함한다.
헤더 파일은 다른 파일에서 구현한 함수와 클래스의 선언을 포함한다.
(내부에서만 사용하는 함수는 헤더파일에서 생략한다.)
herberts/math_functions.hpp
#ifndef HERBERTS_MATH_FUNCTIONS_INCLUDE
#define HERBERTS_MATH_FUNCTIONS_INCLUDE
typedef double hreal;
hreal sine(hreal);
hreal cosine(hreal);
// ...
#endif
herberts/math_functions.cpp
#include <herberts/math_functions.hpp>
hreal divide_by_square(hreal x, hreal y){ /* ... */ }
hreal sine(hreal){ /* ... */ }
hreal cosine(hreal){ /* ... */ }
// ...
소스에서 선언된 함수를 사용할 때, 두 가지 유형으로 사용할 수 있다.
- 헤더 파일(.hpp)를 포함해서 혹은 직접 선언
- 컴파일된 코드(.o)와 링크하거나, 이를 포함하는 라이브러리와 링크

선언은 컴파일러에게 주어진 서명이 있는 함수가 코드 어딘가에 있으며,
컴파일 단위에서 호출될 수 있음을 알린다.
(링크 단계에서 함수 호출을 실제 코드와 결합함)
링크 문제
컴파일러는 함수 및 변수들을 링크 중에 심볼로 표시한다.
C++은 네임 맹글링(Name Mangling)을 사용하는데,
이 때 네임을 타입과 네임스페이스 정보로 생성한다.

링크 실패 가능 조건
- 심볼(함수나 변수)를 찾을 수 없는 경우
- 심볼이 두 번 발견되는 경우
- main 함수가 없는 경우

(모든 소스코드가 호환가능한 컴파일러로 컴파일되지 않을 경우, 네임 맹글링이 다른 이름으로 선언될 수 있다.)
// herbert/math_functions.hpp
double square(double x){ return x*x; }
double pi=3.141592653589793238462;
많은 수학 함수 라이브러리의 헤더파일은 위와 같은 정의를 포함한다.

재정의 문제를 해결하기 위해서 static을 사용할 수 있다.
static double square(double x){ return x*x; }
static 함수는 번역 단위에 지역 함수를 선언한다.
(내부 링크; Internal Linkage)

하지만, 내부 링크를 사용하면, 선언한 숫자만큼 코드가 복제된다.
(inline 지정자가 없는 함수는 외부 링크를 가진다.)

혹은 아래와 같이 hpp에서는 선언만 하고, 이를 cpp에 정의할 수 있다.
// herbert/math_function.hpp
double square(double x);
// herbert/math_function.cpp
double square(double x){
return x*x;
}
길이가 짧은 함수는 inline이어야 하며, 헤더 파일에 정의한다.
길이가 긴 함수는 헤더 파일에 선언하고, 소스 파일에 정의한다.
데이터도 동일하게 static으로 선언해서 사용할 수 있다.
(static으로 선언하면, 모든 번역 단위로 복제된다.)

혹은 extern을 이용해서 헤더 파일에 선언해서 사용할 수 있다.
// herberts/math_function.hpp
extern double pi;
// herberts/math_function.cpp
double pi=3.141592653589793238462;
const로 선언된 상수는 내부 링크를 갖고 있으며 헤더 파일에 안정하게 정의 가능하다.
//herberts/math_functions.hpp
const double pi=3.141592653589793238462;
C 코드에 컴파일
많은 과학 라이브러리들은 C코드로 구현되어 있다.(PETSc 등)
이와 같이 C로 구현된 라이브러리를 C++ 소프트웨어에서 사용하기 위한 두 가지 선택 사항이 있다.

- C 코드를 C++ 컴파일러로 컴파일한다.
- 컴파일된 코드를 링크한다.

대부분의 C 프로그램은 C++ 컴파일러로 컴파일 가능하다.
하지만, C에는 네임 맹글링이 없기 때문에, C 컴파일러와 C++ 컴파일러는 서로 다른 심볼에 매핑한다.
extern "C" double cubic_root(double);
extern "C" double fifth_root(double);
혹은
extern "C"{
double cubic_root(double);
double fifth_root(double);
}
헤더 파일을 사용하는 경우
extern "C"{
#include <herberts/good_ole_math_functions.h>
}
<cmath> 와 같은 C 라이브러리(for C++)은 내부에 <math.h>에 대하여 extern “C”로 구현되어 있다.

extern “C”를 사용하지 않고 각각 컴파일러(gcc, g++)로 컴파일한 이후, 링크하게 되면
다른 심볼을 가지게 되어 오류가 발생할 수 있다.
#ifdef __cplusplus
extern "C"{
#endif
// ...
#ifdef __cplusplus
}
#endif
위와 같은 양식으로 C 라이브러리를 생성하게 되면, 이는 C++와 C 모두에서 사용가능하게 할 수 있다.

gcc는 java와의 링크도 지원한다.
extern “Java"